package com.neusoft.neuiotms.dcvm.repository.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import com.neusoft.bizcore.web.jpa.repository.AbstractRepository;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.neuiotms.dcvm.model.Alarm;
import com.neusoft.neuiotms.dcvm.model.QAlarm;
import com.neusoft.neuiotms.dcvm.repository.CustomizedAlarmRepository;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.Tuple;
import com.querydsl.jpa.impl.JPAQuery;

public class CustomizedAlarmRepositoryImpl extends AbstractRepository implements CustomizedAlarmRepository {

    @Override
    public Page<Alarm> search(final Pageable pageable, final Searchable searchable) {
        final QAlarm qAlarm = QAlarm.alarm;
        final BooleanBuilder where = this.buildWhere(searchable);
        final JPAQuery<Alarm> query = this.query().selectFrom(qAlarm);
        query.where(where);
        return super.search(query, pageable);
    }

    @Override
    public List<Alarm> search(final Searchable searchable) {
        final QAlarm qAlarm = QAlarm.alarm;
        final BooleanBuilder where = this.buildWhere(searchable);
        final JPAQuery<Alarm> query = this.query().selectFrom(qAlarm);
        query.where(where);
        return query.fetch();
    }

    private BooleanBuilder buildWhere(final Searchable searchable) {
        final QAlarm qAlarm = QAlarm.alarm;
        final BooleanBuilder where = new BooleanBuilder();
        where.and(super.equalsStr(qAlarm.locationCode, searchable, "locationCode"));
        where.and(super.afterOrEqualsDate(qAlarm.alarmTime, searchable, "startTime"));
        where.and(super.beforeOrEqualsDate(qAlarm.alarmTime, searchable, "endTime"));
        where.and(super.inStrings(qAlarm.locationCode, searchable, "locationCodeList"));
        return where;
    }

    @Override
    protected Class<?> getModelClass() {
        return Alarm.class;
    }

    @Override
    public List<Map<String, Object>> statsByLocation() {
        final QAlarm qAlarm = QAlarm.alarm;
        final List<Tuple> result =
                this.query().select(qAlarm.locationCode, qAlarm.locationName, qAlarm.count()).from(qAlarm)
                        .groupBy(qAlarm.locationCode, qAlarm.locationName).fetch();
        final Map<String, Long> map = new HashMap<>();
        for (final Tuple row : result) {
            map.put(row.get(qAlarm.locationCode), row.get(qAlarm.count()));
        }
        final List<Map<String, Object>> data = result.stream().map(row -> {
            final Map<String, Object> item = new HashMap<>();
            item.put("locationCode", row.get(qAlarm.locationCode));
            item.put("locationName", row.get(qAlarm.locationName));
            item.put("count", row.get(qAlarm.count()));
            return item;
        }).collect(Collectors.toList());

        return data;
    }

}
